package smtp;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.text.SimpleDateFormat;
import java.util.LinkedList;

import javax.mail.Address;
import javax.mail.Flags.Flag;
import javax.mail.MessagingException;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import com.sun.mail.imap.IMAPMessage;

/**
 * @author chandlerr, liw, wendlandts
 * 
 * Creates a cell for a JList of messages
 * The cell contains information on an IMAPMessage
 * 
 * Displays the following:
 * checkbox | flaggedIcon | mailIcon | attachmentIcon | from | subject | date
 * 
 * The checkbox was intended to allow the user to select a set of messages
 * for deletion or similar operation.  Problems were encountered in setting the behavior of
 * a checkbox within a JList cell.  UI-intense and not a priority.
 */
public  class EmailListCellRenderer implements ListCellRenderer {
	ListDataListener dataListener;
	LinkedList<IMAPMessage> checkedMessages;
	
	// the width and height of the icons indicated in the constructor
	private static int iconWidth = 16;
	private static int iconHeight = 16;

	private static SimpleDateFormat dateRecievedFormat = new SimpleDateFormat("EEE, d MMM yyyy hh:mm aaa");


	// Flags:
	// answered
	// seen
	// (implicitly) unopenned
	// attachment
	// flagged
	// deleted (Goes in recycle bin?)
	// draft (Goes in drafts?)
	// $MDNSent (if supported)?? // not used

	ImageIcon replied, seen, unopenned, unopennedNew, attachment, flagged;

	public EmailListCellRenderer() {
		replied = new ImageIcon("./resources/mail-forward.png", "Replied");
		seen = new ImageIcon("./resources/mail-open.png", "Read");
		unopenned = new ImageIcon("./resources/mail.png", "Unread");
		unopennedNew = new ImageIcon("./resources/mail_blue.png", "New");
		attachment = new ImageIcon("./resources/paper-clip.png", "Attachment");
		flagged = new ImageIcon("./resources/flag.png", "Flagged");
		
		// Attempted to keep track of check items here.
		// checkedMessages = new LinkedList<IMAPMessage>();
		dataListener = null;
	}

	// checkbox | flaggedIcon | mailIcon | attachmentIcon | from | subject | date
	/**
	 * Method called by JList to render a cell
	 */
	public Component getListCellRendererComponent(final JList list,
			Object value,
			int index,
			boolean isSelected,
			boolean cellHasFocus) {
		final JPanel cell;

		// A 1x7 "row".  Fixed width for "columns"
		FlowLayout flowLayout = new FlowLayout();
		flowLayout.setHgap(4);
		flowLayout.setVgap(2);
		flowLayout.setAlignment(FlowLayout.LEFT);
		cell = new JPanel(flowLayout);


		// JLabelSet is a private data class
		// It represents the different fields appearing in an email cell
		JLabelSet labels = new JLabelSet(list.getWidth() - iconWidth); // save room for the check box
		final JCheckBox checkBox = new JCheckBox();

		if(value.getClass().equals(IMAPMessage.class)){
			final IMAPMessage msg = (IMAPMessage)value;

			// First, get the flags for the message and set the JLabelSet appropriately
			labels.mailIcon.setIcon(this.unopenned);

			// Get the system flags
			Flag[] systemFlags = null;
			try {
				systemFlags = msg.getFlags().getSystemFlags();
			} catch (MessagingException e1) {
				System.out.println ("Exception in getting flags for message: " + msg + 
						"\nError message: " + e1.getLocalizedMessage());
				e1.printStackTrace();
			}

			// For each system flag, determine its value
			// Then, edit JLabelSet as needed
			for (Flag flag: systemFlags){
				if(flag == Flag.ANSWERED){
					labels.mailIcon.setIcon(this.replied);
				} else if (flag == Flag.FLAGGED){
					labels.flaggedIcon.setIcon(this.flagged);
				} else if (flag == Flag.RECENT){
					// Everything is recent!
					//labels.mailIcon.setIcon(this.unopennedNew);
					//labels.subject.setFont(labels.subject.getFont().deriveFont(Font.BOLD));
					//cell.setBackground(new Color(206,242,255));
				} else if (flag == Flag.SEEN){
					labels.mailIcon.setIcon(this.seen);
				}
			}
			

			if(isSelected){
				cell.setBackground(cell.getBackground().darker());
			}
			
			if(cellHasFocus){
				cell.setBackground(cell.getBackground().darker());
			}

			// Next, set the text fields (sender, subject, date, attachment)

			// Set the sender field
			try {				
				// getting sender causes problems
				// get the from
				labels.from.setText(addressesToString(msg.getFrom()));
				
			} catch (MessagingException e) {
				System.out.println("Error getting 'from' of message: " + msg);
				e.printStackTrace();
			}

			// Set the subject field
			try {
				labels.subject.setText(msg.getSubject());
			} catch (MessagingException e) {
				System.out.println ("Exception in getting subject for message: " + msg + 
						"\nError message: " + e.getLocalizedMessage());
				e.printStackTrace();
			}

			// Set the date field
			try {
				labels.date.setText(dateRecievedFormat.format(msg.getSentDate()));
			} catch (MessagingException e) {
				System.out.println ("Exception in getting sent date for message: " + msg + 
						"\nError message: " + e.getLocalizedMessage());
				e.printStackTrace();
			}

			// Set the attachment field
			String contentType = null;
			try {
				contentType = msg.getContentType();
			} catch (MessagingException e) {
				System.out.println ("Exception in getting content type for message: " + msg + 
						"\nError message: " + e.getLocalizedMessage());
				e.printStackTrace();
			}
			
			//if it's not purely text, then we assume it has some downloadable file
			// does not check content-disposition (inline vs attachment)  Change this??
			if(!(contentType.contains("text/plain") ||
					contentType.contains("multipart/digest") || 
					contentType.contains("multipart/message"))){
				labels.attachmentIcon.setIcon(this.attachment);
			}
			
			/* 
			 * DOES NOT WORK
			 * The JList handles all clicks and does not pass them down to the checkbox
			 * 
			// Create checkbox.  Listener commented out because no actions are taken when the box is checked/unchecked
			checkBox.addMouseListener(new MouseListener(){

				@Override
				public void mouseClicked(MouseEvent event) {
					checkBox.setSelected(!(checkBox.isSelected()));
				}

				@Override  ------ A lot more methods removed to save space
				}
				});
			checkBox.addItemListener(new ItemListener(){

				@Override
				public void itemStateChanged(ItemEvent event) {
					if(event.getStateChange() == ItemEvent.SELECTED){
						checkBox.setSelected(true);
						checkedMessages.add(msg);
						cell.setBackground(cell.getBackground().darker());
					} else if (event.getStateChange() == ItemEvent.DESELECTED){
						checkBox.setSelected(false);
						checkedMessages.remove(msg);
						cell.setBackground(cell.getBackground().brighter());
					}
				}

	    	});
	    	*/

		}

		//Next, put the collected data in the JLabelSet into a JPanel

		// Put Components in in this order:
		// checkbox | flaggedIcon | mailIcon | attachmentIcon | from | subject | date
		
		checkBox.setIconTextGap(0);
		checkBox.setMargin(new Insets(0,0,0,0));
		//checkBox.setSelected(isSelected);
		checkBox.setMaximumSize(new Dimension(iconWidth-2, iconHeight-2)); //hopefully limits the checkbox size.  Aiming to keep uniform column width

		// add the elements in in order
		cell.add(checkBox);		
		cell.add(labels.flaggedIcon);
		cell.add(labels.mailIcon);
		cell.add(labels.attachmentIcon);
		cell.add(labels.from);
		cell.add(labels.subject);
		cell.add(labels.date);



		return cell;
	}

	private String addressesToString(Address[] addresses){
		String addressString = "";
		if((addresses != null) && (addresses.length > 0 )){
			for(Address address: addresses){
				addressString += ", " + address.toString();
			}
			addressString = addressString.substring(2);
		}
		return addressString;
	}

	private class JLabelSet {
		JLabel mailIcon;
		JLabel flaggedIcon;
		JLabel attachmentIcon;
		JLabel subject;
		JLabel from;
		JLabel date;

		JLabelSet(int width){
			// width is split over:
			// icon icon icon txt txt txt
			// txt fields get all that's left
			int textWidth = width/3 - iconWidth;
			Dimension iconDim = new Dimension(iconWidth, iconHeight);
			mailIcon = JLabel(iconDim);
			flaggedIcon = JLabel(iconDim);
			attachmentIcon = JLabel(iconDim);

			Dimension textDim = new Dimension(textWidth, iconHeight);
			subject = JLabel(textDim);
			from = JLabel(textDim);
			date = JLabel(textDim);
		}

		private JLabel JLabel(Dimension d){
			JLabel label = new JLabel(null, null, SwingConstants.LEFT);
			label.setMaximumSize(d);
			label.setPreferredSize(d);
			label.setMinimumSize(d);
			label.setIconTextGap(0);
			return label;
		}
	}
	
	/**
	 * Would make changes to the checkboxes based on content changes in the JList
	 * Not used.
	 * @return
	 */
	public ListDataListener getDataListener(){
		if(dataListener == null){
			dataListener = new ListDataListener(){

				@Override
				public void contentsChanged(ListDataEvent e) {
					checkedMessages.clear();
				}

				@Override
				public void intervalAdded(ListDataEvent e) {
					//no change
				}

				@Override
				public void intervalRemoved(ListDataEvent e) {
					for(int x = e.getIndex0(); x < e.getIndex1(); x++){
						checkedMessages.remove(((ListModel) e.getSource()).getElementAt(x));
					}
				}
				
			};
		}
		
		return dataListener;
	}
	
	
	public IMAPMessage[] getCheckedMessages(){
		return checkedMessages.toArray(new IMAPMessage[checkedMessages.size()]);
	}
}